.com
Hosted by:
Unit testing expertise at your fingertips!
Home | Discuss | Lists

Garbage-Collected Teardown

The book has now been published and the content of this chapter has likely changed substanstially.
Please see page 500 of xUnit Test Patterns for the latest information.
How do we tear down the Test Fixture?

We let the garbage collection mechanism provided by the programming language clean up after our test.

Sketch Garbage-Collected Teardown embedded from Garbage-Collected Teardown.gif

A large part of making tests repeatable and robust is ensuring that the test fixture is torn down after each test. In languages the have garbage collection, much of the tear down can happen automatically if we refer to resources via instance variables.

How It Works

Many of the objects created during the course of our test (including both fixture setup and exercising the system under test (SUT)) are transient objects that are only kept alive as long as there is a reference to them somewhere in the program that created them. The garbage collection mechanisms of modern languages use various algorithms to detect "garbage". What is most important, though, is how they determine that something is not garbage: Any object that is reachable from any other live object or from global (i.e. static) variables will not be garbage collected.

When running our tests, the Test Automation Framework (page X) (assuming is implements Test Discovery (page X)) creates a Testcase Object (page X) for each Test Method (page X) in our Testcase Class (page X) and adds them to a Test Suite Object (page X). Whenever a new test run is started, it typically throws away the existing test suite and builds a new one (to be sure everything is fresh). By throwing away the old test suite, any objects referenced only by instance variables in those tests become candidates for garbage collection.

When To Use It

We should use Garbage-Collected Teardown whenever we possibly can as it will save us a lot of effort!

If we are using a Shared Fixture (page X), we won't be able to use Garbage-Collected Teardown unless we do something fancy to hold the reference to the fixture in such a way that it will go out of scope when our test suite has finished running.

If our programming in an environment that doesn't support garbage collection, or we have resources that don't get garbage collected automatically (things like files, sockets, records in a database), we'll need to be destroy or free them explicitly. We could use any of Inline Teardown (page X), Implicit Teardown (page X) or Automated Teardown (page X) to ensure that they are freed up properly.

Implementation Notes

Some members of the xUnit family and some IDE's go so far as to replace the classes each time the test suite is run. We may see this show up as an option called "Reload Classes" or it may be forced upon us. Be careful if we decide to take advantage of this feature to use Garbage-Collected Teardown with fixture holding class variables as we may find our tests stop running if we change IDE's or try running our tests from the command line (e.g. from "Cruise Control" or a build script.)

Motivating Example

The test below creates some in-memory objects during fixture setup and explicitly destroys them using Inline Teardown. (We could also have used Implicit Teardown in this example but that just makes it harder for readers to see what is going on.)

   public void testCancel_proposed_UIT() {
      // setup fixture:
      Flight proposedFlight = createAnonymousProposedFlight();
      // exercise SUT
      proposedFlight.cancel();
      // verify outcome:
      try{
         assertEquals( FlightState.CANCELLED, proposedFlight.getStatus());
      } finally {
         // tearDown:
         proposedFlight.delete();
         proposedFlight = null;
      }
   }
Example UnecessaryInlineTeardown embedded from java/com/clrstream/ex6/services/test/SetupStyles.java

Because these objects are not persistent in any way, the destruction code is unnecessary and just makes the test more complicated and harder to understand.

Refactoring Notes

To convert to Garbage-Collected Teardown, we need only remove the unnecessary cleanup code. If we had been using a class variable to hold the reference to the object, we would have had to convert it to either an instance variable or a local variable both of which would have moved us from a Shared Fixture to a Fresh Fixture (page X).

Example: Garbage-Collected Teardown

In this reworked test, we are letting Garbage-Collected Teardown do the job for us.

   public void testCancel_proposed_GCT() {
      // fixture setup:
      Flight mutableFlight = createAnonymousProposedFlight();
      // exercise SUT
      mutableFlight.cancel();
      // verify outcome\
      assertEquals( FlightState.CANCELLED, mutableFlight.getStatus());
      // tearDown:
      //  Garbage collected when mutableFlight goes out of scope
   }
Example GarbageCollectedTeardown embedded from java/com/clrstream/ex6/services/test/SetupStyles.java

Note how much simpler the test has become!



Page generated at Wed Feb 09 16:39:36 +1100 2011

Copyright © 2003-2008 Gerard Meszaros all rights reserved

All Categories
Introductory Narratives
Web Site Instructions
Code Refactorings
Database Patterns
DfT Patterns
External Patterns
Fixture Setup Patterns
Fixture Teardown Patterns
Front Matter
Glossary
Misc
References
Result Verification Patterns
Sidebars
Terminology
Test Double Patterns
Test Organization
Test Refactorings
Test Smells
Test Strategy
Tools
Value Patterns
XUnit Basics
xUnit Members
All "Fixture Teardown Patterns"
Garbage-Collected Teardown
Inline Teardown
Implicit Teardown
Automated Teardown